package com.harboursoftware.xstorage.operations;

import java.util.Map;

import com.harboursoftware.xstorage.fs.XFileSystem;
import com.harboursoftware.xstorage.model.XBucket;
import com.harboursoftware.xstorage.model.XElement;
import com.harboursoftware.xstorage.model.XObject;

public class OperationFactory {
    private XFileSystem fileSystem;

    public OperationFactory(XFileSystem fileSystem) {
        this.fileSystem = fileSystem;
    }

    /**
     * create an Operation(e.g. PutBucket,GetObject...). operation name= method + target
     * 
     * @param method
     *            http method
     * @param target
     *            operation target
     * @return the operation
     */
    public Operation createOperation(String method, XElement target, Map<String, String> parameters) {
        Operation operation = null;
        if (target instanceof XObject) {
            operation = createObjectOperation(method, parameters);
        } else if (target instanceof XBucket) {
            operation = createBucketOperation(method, parameters);
        } else { // target instanceof XService
            return createBucketOperation(method);
        }
        operation.setFileSystem(fileSystem);
        return operation;
    }

    /**
     * create operations on object.
     * 
     * @param method
     * @param object
     * @param parameters
     * @return
     */
    private Operation createObjectOperation(String method, Map<String, String> parameters) {
        if (method.equals("GET")) {
            if (parameters.containsKey("acl")) {
                return new GetObjectAcl();
            } else {
                return new GetObject();
            }

        } else if (method.equals("PUT")) {
            return new PutObject();

        } else if (method.equals("POST")) {
            return new PostObject();
        } else if (method.equals("DELETE")) {
            return new DeleteObject();
        } else if (method.equals("COPY")) {
            return new CopyObject();
        } else if (method.equals("HEAD")) {
            return new HeadObject();
        } else {
            throw new IllegalArgumentException("argument method is invalid");
        }
    }

    /**
     * create operations on bucket.
     * 
     * @param method
     * @param object
     * @param parameters
     * @return
     */
    private Operation createBucketOperation(String method, Map<String, String> parameters) {
        if (method.equals("GET")) {
            if (parameters.containsKey("acl")) {
                return new GetBucketAcl();
            } else {
                return new GetBucket();
            }
        } else if (method.equals("PUT")) {
            if (parameters.containsKey("acl")) {
                return new PutBucketAcl();
            } else {
                return new PutBucket();
            }

        } else if (method.equals("DELETE")) {
            return new DeleteBucket();
        } else {
            throw new IllegalArgumentException("argument method is invalid");
        }
    }

    /**
     * create operations on service.
     * 
     * @param method
     * @return
     */
    private Operation createBucketOperation(String method) {
        if ("GET".equals(method)) {
            return new GetService();
        } else {
            throw new IllegalArgumentException("argument method is invalid");
        }
    }
}
